package ilender.background;

import java.util.List;
import java.util.HashMap;
import java.util.TreeSet;

import org.apache.ibatis.session.*;
import org.joda.time.DateTime;

import com.google.gson.*;

import lombok.*;

import ilender.util.*;
import ilender.exceptions.UnauthorizedGraphActionException;
import ilender.facebook.FBNotification;
import ilender.facebook.FBUser;
import ilender.facebook.GraphAPI;
import ilender.mappers.*;
import ilender.models.*;


/**
 * Called periodically to update data from Facebook.
 *
 * Updates users' name and location.
 */
public class UpdaterFromFacebook implements Runnable {

	@Override
	public void run() {
		try(SqlSession session=MyBatisTools.openSession()){
			val usersMapper=session.getMapper(UsersMapper.class);
			val users=usersMapper.usersToUpdate();
			JsonArray request=new JsonArray();
			val usersById=new HashMap<Long,MUser>();
			System.out.println(users);
			for(val user : users){
				request.add(JsonTools.makeObject("method", "GET",
							"relative_url", String.format("%s?fields=id,name,location",user.getId())));
				usersById.put(user.getId(),user);
			}
			val locationIdsToCheck=new TreeSet<Long>();
			val locationIdsByUserId=new HashMap<Long,Long>();
			if(0<request.size()){
				for (JsonElement entry : GraphAPI.getInstance().batchRequest(request)){
					JsonObject entryAsObject = entry.getAsJsonObject();
					System.out.printf("%s\t%s\n",
							entryAsObject.get("id").getAsLong(),
							entryAsObject.get("name").getAsString());
					val user=usersById.get(entryAsObject.get("id").getAsLong());
					user.setName(entryAsObject.get("name").getAsString());
					if(entryAsObject.has("location")){
						locationIdsToCheck.add(entryAsObject.getAsJsonObject("location").get("id").getAsLong());
						user.setLocation_name(entryAsObject.getAsJsonObject("location").get("name").getAsString());
						locationIdsByUserId.put(user.getId(),entryAsObject.getAsJsonObject("location").get("id").getAsLong());
					}
				}
			}
			request=new JsonArray();
			for(val locationId : locationIdsToCheck){
				request.add(JsonTools.makeObject("method","GET",
							"relative_url",String.format("%s?fields=location",locationId)));
			}
			val locationsById=new HashMap<Long,JsonObject>();
			for(JsonElement entry : GraphAPI.getInstance().batchRequest(request)){
				JsonObject entryAsObject=entry.getAsJsonObject();
				locationsById.put(entryAsObject.get("id").getAsLong(),entryAsObject.getAsJsonObject("location"));
			}
			for(val user : users){
				val locationId=locationIdsByUserId.get(user.getId());
				if(null!=locationId){
					val locationJson=locationsById.get(locationId);
					user.setLocation_latitude(locationJson.get("latitude").getAsDouble());
					user.setLocation_longitude(locationJson.get("longitude").getAsDouble());
				}
				user.save(usersMapper);
			}
			session.commit();
		}catch(Exception e){
			e.printStackTrace();
		}
	}
}
